#include "Retransmit.hpp"

using namespace BFT::messages;

Retransmit::Retransmit(uint32_t _client, uint32_t _seqNo, uint32_t _sender)
	: MacArrayMessage::MacArrayMessage(RETRANSMIT, computeSize(), _sender, BFT::Parameters::getExecutionCount())
{
	client = _client;
	seqNo = _seqNo;
	
	int bytes_size;
	boost::shared_ptr<char> bytes = getBytes(bytes_size);
	int offset = getOffset();
	
	//write the client
	*(uint32_t*)(bytes.get()+offset) = htonl(client);
	offset += CLIENT_ID_SIZE;
	
	//write the sequence number
	*(uint32_t*)(bytes.get()+offset) = htonl(seqNo);
}

Retransmit::Retransmit(boost::shared_ptr<char> _bytes, int _bytes_size)
	: MacArrayMessage::MacArrayMessage(_bytes, _bytes_size)
{
	if (getTag() != RETRANSMIT)
	{
		fprintf(stderr,"trying to build a retransmit message from invalid bytes. expected tag: %d, actual tag: %d\n",RETRANSMIT, getTag());
		exit(111);
	}
	
	unsigned int offset = getOffset();
	
	//read the client id
	client = ntohl( *(uint32_t*)(_bytes.get()+offset));
	offset += CLIENT_ID_SIZE;
	
	//read the sequence number
	seqNo = ntohl( *(uint32_t*)(_bytes.get()+offset));
	offset += SEQUENCE_NUMBER_SIZE;
	
	if (offset != _bytes_size - getAuthenticationSize())
	{
		fprintf(stderr,"trying to build a retransmit message from invalid bytes\n");
		exit(112);
	}	
}

bool Retransmit::equals(boost::shared_ptr<Retransmit> _other_r)
{
	return MacArrayMessage::equals(_other_r) && 
	       seqNo == _other_r.get()->getSequenceNumber() &&
	       client == _other_r.get()->getClient();
}

bool Retransmit::matches(boost::shared_ptr<VerifiedMessageBase> _other_vmb)
{
	//TODO find a better way to downcast
	//boost::shared_ptr<Retransmit> other_r = boost::static_pointer_cast<Retransmit>( _other_vmb);
		
	int r_size;
	boost::shared_ptr<char> r_bytes = _other_vmb.get()->getBytes(r_size);
	boost::shared_ptr<Retransmit> other_r (new Retransmit(r_bytes,r_size));
	
	return seqNo == other_r.get()->getSequenceNumber() && client == other_r.get()->getClient();
}

void Retransmit::printInfo()
{
	fprintf(stderr,"Retransmit information : \n");
	fprintf(stderr,"cleint:%d\nseqNo: %d\n",client,seqNo);
}
